﻿/******************************************************
* author :  cwj
* email  :  chenwenji_360@live.com 
* history:  created by cwj 2015/7/24 23:08:22 
* clrversion :4.0.30319.18444
******************************************************/

using Machine.DataAccess.Linq.Relation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Machine.DataAccess.Linq
{
    class SqliteFormat : SetFormatBase
    {
        public SqliteFormat(ProviderElement providerElement) : base(providerElement) { }

        protected override Expression VisitSelect(SelectExpression select)
        {
            if(select.IsDelete)
            {
                this.build.Append("Delete From ");
                var tableExpression_delete = select.From as TableExpression;
                this.build.Append(tableExpression_delete.TableName);
                //this.Visit(tableExpression_delete);
                this.build.Append(" Where ");
                this.Visit(select.Where);
                this.build.Replace("as t0", "");
                this.build.Replace("t0.", "");
                return select;
            }

            if(select.IsUpdate)
            {
                this.build.Append("Update ");
                var tableExpression_delete = select.From as TableExpression;
                this.Visit(tableExpression_delete);
                this.Visit(select.UpdateSelect);
                this.build.Append(" Where ");
                this.Visit(select.Where);
                this.build.Replace("as t0", "");
                this.build.Replace("t0.", "");
                return select;
            }

            if (select.IsCount)
            {
                this.build.Append("Select Count(*) From ( ");
            }

            this.build.Append("Select ");
            //if (select.Top > 0)
            //{
            //    this.build.Append("Top(");
            //    this.build.Append(select.Top);
            //    this.build.Append(") ");
            //}
            if (select.IsDistinct)
            {
                this.build.Append(" Distinct ");
            }
            for (int i = 0; i < select.Colums.Count(); i++)
            {
                reNameColum = true;
                if (i > 0) this.build.Append(",");
                var colum = select.Colums.ElementAt(i);
                var columExpression = this.Visit(colum.ColumExpression) as ColumExpression;
                if (columExpression == null || columExpression.Name != colum.ColumName)
                {
                    this.build.Append(" as ");
                    this.build.Append(columExpression.Name);
                }
                reNameColum = false;
            }
            //if (select.Colums.Count() == 0)
            //{
            //    this.build.Append(" Count(*) ");
            //}
            if (select.From != null || select.JoinSingleType.Count()>0)
            {
                this.build.Append(" From ");
                var tableExpression = select.From as TableExpression;
                this.VisitSource(tableExpression);
                if (select.JoinSingleType.Count() > 0)
                {
                    this.VistJoinSingleType(tableExpression, select.JoinSingleType);
                    //foreach (var item in select.JoinSingleType)
                    //{
                    //    this.build.Append(" left join ");
                    //    this.VisitSource(item);
                    //    this.build.Append(" on ");
                    //    var schem = Config.Instance.GetDbSchemInfo(this.ProviderElement).GetSchem(tableExpression.Type);
                    //    if (!schem.ForeignKeys.ContainsKey(item.TableName))
                    //    {
                    //        foreach (var innnerItem in select.JoinSingleType)
                    //        {
                    //            schem = Config.Instance.GetDbSchemInfo(this.ProviderElement).GetSchem(innnerItem.Type);
                    //            if (schem.ForeignKeys.ContainsKey(item.TableName))
                    //            {
                    //                var fk = schem.ForeignKeys[item.TableName];
                    //                this.build.Append(string.Format(" {0}.{1} = {2}.{3} ",
                    //                    innnerItem.TableArg, fk.From, item.TableArg, fk.To));
                    //            }
                    //        }
                    //    }
                    //    else
                    //    {
                    //        var fk = schem.ForeignKeys[item.TableName];
                    //        this.build.Append(string.Format(" {0}.{1} = {2}.{3} ",
                    //            tableExpression.TableArg, fk.From, item.TableArg, fk.To));
                    //    }
                        //throw new Exception("数据库没有这个外键");
                        //fk.ForeignKeys.FirstOrDefault(x=>x.From == select)
                    //}
                }
            }
            if (select.Where != null)
            {
                this.build.Append(" Where ");
                this.Visit(select.Where);
                //if (select.Skip > 0) this.VisitSkip(select);
            }
            if (select.Like != null)
            {
                if (select.Where != null) this.build.Append(" And ");
                else this.build.Append(" Where ");
                this.Visit(select.Like);
            }
            if (select.OrderBy != null && select.OrderBy.Count() > 0 && select.Colums.Count() > 0)
            {
                this.build.Append(" Order By ");

                for (int i = 0; i < select.OrderBy.Count(); i++)
                {
                    if (i > 0) this.build.Append(",");
                    var item = select.OrderBy.ElementAt(i).ColumExpression as ColumExpression;
                    this.build.Append(item.TableArg);
                    this.build.Append(".");
                    this.build.Append(item.Name);
                }
                this.build.Append(" ");
                this.build.Append(select.OrderByType);
            }
            if (select.Top != 0 || select.Skip != 0)
            {
                this.VisitSkip(select);
            }

            if (select.IsCount)
            {
                this.build.Append(" )  as t0");
            }
            return select;
        }

        protected override void VisitSkip(SelectExpression select)
        {
            this.build.Append(string.Format(" limit {0},{1}", select.Skip, select.Top));
            //if (select.Where != null)
            //{
            //    this.build.Append(" And ");
            //}
            //var colum = select.OrderBy.FirstOrDefault();
            //this.build.Append(string.Format("{0}.{1}", colum.ColumExpression.TableArg, colum.ColumName));
            //this.build.Append(" Not In ");
            //this.build.Append(string.Format("(Select top {0} {1} From {2} Order By {1} {3})",
            //    select.Skip,
            //    colum.ColumName,
            //    (select.From as TableExpression).TableName,
            //    select.OrderByType));
        }
    }
}
